package com.jingdong.callback;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jingdong.callback.model.*;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.*;

/**
 * 京东配送回调SDK
 * 
 * 用于向海博技术服务平台发送京东配送订单状态变更、骑手信息变更、费用信息变更等回调
 * 
 * @author SDK Team
 * @version 1.0.0
 */
public class JingdongCallbackSDK {
    
    private static final Logger logger = LoggerFactory.getLogger(JingdongCallbackSDK.class);
    
    /**
     * 版本号
     */
    public static final String VERSION = "1.0.0";
    
    /**
     * 海博技术服务平台回调接口地址
     */
    public static final String CALLBACK_URL_TEST = "https://pre-carrieropen.hiboos.com/api/delivery/statusCallback";
    public static final String CALLBACK_URL_SANDBOX = "https://carrieropen-tool.hiboos.com/api/delivery/statusCallback";
    public static final String CALLBACK_URL_PROD = "https://carrieropen.hiboos.com/api/delivery/statusCallback";
    
    /**
     * 请求超时时间（毫秒）
     */
    public static final int TIMEOUT = 120000;
    
    /**
     * 重试次数
     */
    public static final int MAX_RETRY = 3;
    
    /**
     * 京东接口返回结果Code
     */
    public static final int ERROR_SUCCESS = 0;
    public static final int ERROR_SYSTEM_ERROR = 1;
    public static final int ERROR_PARAM_ERROR = 2;
    public static final int ERROR_SIGN_ERROR = 3;
    public static final int ERROR_UNAUTHORIZED = 4;
    public static final int ERROR_RATE_LIMIT = 5;
    public static final int ERROR_OTHER = 9;
    public static final int ERROR_NO_CAPACITY = 10;
    public static final int ERROR_ORDER_NOT_EXIST = 101;
    public static final int ERROR_ORDER_COMPLETED = 102;
    public static final int ERROR_SERVICE_NOT_OPEN = 103;
    public static final int ERROR_OUT_OF_RANGE = 104;
    public static final int ERROR_APPOINTMENT_TIME = 105;
    public static final int ERROR_CAPACITY_SHORTAGE = 106;
    public static final int ERROR_ACCOUNT_BALANCE = 107;
    public static final int ERROR_NO_APPOINTMENT = 108;
    public static final int ERROR_NO_REVERSE_ORDER = 109;
    public static final int ERROR_TIP_LIMIT = 110;
    public static final int ERROR_TIP_MAX = 111;
    public static final int ERROR_NO_RIDER_LOCATION = 112;
    public static final int ERROR_CARRIER_MISMATCH = 301;
    public static final int ERROR_DELIVERY_ID_MISMATCH = 302;
    public static final int ERROR_WAYBILL_NOT_EXIST = 303;
    public static final int ERROR_RIDER_CODE_ERROR = 501;
    public static final int ERROR_RIDER_LIMIT = 502;
    public static final int ERROR_RIDER_CANNOT_ACCEPT = 503;
    public static final int ERROR_FEATURE_NOT_OPEN = 504;
    public static final int ERROR_STORE_CREATE_FAILED = 601;
    public static final int ERROR_STORE_NO_CHANGE = 602;
    
    private final SDKConfig config;
    private final ObjectMapper objectMapper;
    private final CloseableHttpClient httpClient;
    private JedisPool jedisPool;
    
    /**
     * 构造函数
     * 
     * @param config 配置信息
     */
    public JingdongCallbackSDK(SDKConfig config) {
        this.config = config;
        this.objectMapper = new ObjectMapper();
        this.httpClient = createHttpClient();
        this.initRedis();
        
        logger.info("京东配送回调SDK初始化完成 - 版本: {}, 环境: {}", VERSION, config.getEnvironment());
    }
    
    /**
     * Builder模式构建SDK实例
     */
    public static class Builder {
        private String developerId;
        private String secret;
        private String environment = "test";
        private String redisHost;
        private int redisPort = 6379;
        private int redisDatabase = 0;
        private String redisPassword;
        private int redisTimeout = 3000;
        private boolean enableLog = true;
        private String userAgent = "JingdongCallbackSDK-Java/" + VERSION;
        
        public Builder developerId(String developerId) {
            this.developerId = developerId;
            return this;
        }
        
        public Builder secret(String secret) {
            this.secret = secret;
            return this;
        }
        
        public Builder environment(String environment) {
            this.environment = environment;
            return this;
        }
        
        public Builder redisHost(String redisHost) {
            this.redisHost = redisHost;
            return this;
        }
        
        public Builder redisPort(int redisPort) {
            this.redisPort = redisPort;
            return this;
        }
        
        public Builder redisDatabase(int redisDatabase) {
            this.redisDatabase = redisDatabase;
            return this;
        }
        
        public Builder redisPassword(String redisPassword) {
            this.redisPassword = redisPassword;
            return this;
        }
        
        public Builder redisTimeout(int redisTimeout) {
            this.redisTimeout = redisTimeout;
            return this;
        }
        
        public Builder enableLog(boolean enableLog) {
            this.enableLog = enableLog;
            return this;
        }
        
        public Builder userAgent(String userAgent) {
            this.userAgent = userAgent;
            return this;
        }
        
        public JingdongCallbackSDK build() {
            SDKConfig config = new SDKConfig();
            config.setDeveloperId(developerId);
            config.setSecret(secret);
            config.setEnvironment(environment);
            config.setRedisHost(redisHost);
            config.setRedisPort(redisPort);
            config.setRedisDatabase(redisDatabase);
            config.setRedisPassword(redisPassword);
            config.setRedisTimeout(redisTimeout);
            config.setEnableLog(enableLog);
            config.setUserAgent(userAgent);
            
            return new JingdongCallbackSDK(config);
        }
    }
    
    /**
     * 创建HTTP客户端
     */
    private CloseableHttpClient createHttpClient() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(TIMEOUT)
                .setConnectTimeout(10000)
                .setConnectionRequestTimeout(10000)
                .build();
        
        return HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .build();
    }
    
    /**
     * 初始化Redis连接池
     */
    private void initRedis() {
        if (config.getRedisHost() == null || config.getRedisHost().isEmpty()) {
            logger.info("未配置Redis，将跳过防重复检查");
            return;
        }
        
        try {
            JedisPoolConfig poolConfig = new JedisPoolConfig();
            poolConfig.setMaxTotal(20);
            poolConfig.setMaxIdle(10);
            poolConfig.setMinIdle(5);
            poolConfig.setTestOnBorrow(true);
            poolConfig.setTestOnReturn(true);
            poolConfig.setTestWhileIdle(true);
            
            if (config.getRedisPassword() != null && !config.getRedisPassword().isEmpty()) {
                this.jedisPool = new JedisPool(poolConfig, config.getRedisHost(), config.getRedisPort(), 
                        config.getRedisTimeout(), config.getRedisPassword(), config.getRedisDatabase());
            } else {
                this.jedisPool = new JedisPool(poolConfig, config.getRedisHost(), config.getRedisPort(), 
                        config.getRedisTimeout(), null, config.getRedisDatabase());
            }
            
            // 测试连接
            try (Jedis jedis = jedisPool.getResource()) {
                jedis.ping();
                logger.info("Redis连接成功 - {}:{}/{}", config.getRedisHost(), config.getRedisPort(), config.getRedisDatabase());
            }
            
        } catch (Exception e) {
            logger.error("Redis连接失败: {}", e.getMessage());
            this.jedisPool = null;
        }
    }
    
    /**
     * 发送订单状态回调
     * 
     * @param order 订单信息
     * @param status 新状态
     * @return 回调结果
     */
    public CallbackResult sendStatusCallback(Order order, int status) {
        return sendStatusCallback(order, status, new HashMap<>());
    }
    
    /**
     * 发送订单状态回调
     * 
     * @param order 订单信息
     * @param status 新状态
     * @param extraParams 额外参数
     * @return 回调结果
     */
    public CallbackResult sendStatusCallback(Order order, int status, Map<String, Object> extraParams) {
        try {
            // 防重复机制检查
            boolean isTransfer = Boolean.TRUE.equals(extraParams.get("isTransfer"));
            
            if (!isTransfer && jedisPool != null) {
                String deduplicationKey = "jd_callback_sent_" + order.getId() + "_" + status;
                
                try (Jedis jedis = jedisPool.getResource()) {
                    if (jedis.exists(deduplicationKey)) {
                        String lastSentInfo = jedis.get(deduplicationKey);
                        logger.info("京东状态回调防重复跳过 - 订单ID: {}, 状态: {}, 上次发送: {}", 
                                order.getId(), status, lastSentInfo);
                        
                        CallbackResult result = new CallbackResult();
                        result.setSuccess(true);
                        result.setMessage("防重复跳过发送");
                        result.setDeduplicated(true);
                        return result;
                    }
                    
                    // 记录本次发送
                    Map<String, Object> sendInfo = new HashMap<>();
                    sendInfo.put("order_id", order.getId());
                    sendInfo.put("status", status);
                    sendInfo.put("sent_at", Instant.now().toString());
                    sendInfo.put("timestamp", System.currentTimeMillis() / 1000);
                    sendInfo.put("is_transfer", false);
                    
                    jedis.setex(deduplicationKey, 30, objectMapper.writeValueAsString(sendInfo));
                }
            }
            
            // 构建回调参数
            Map<String, Object> params = buildCallbackParams(order, status, extraParams);
            
            // 发送回调
            Map<String, Object> responseData = sendCallback(params);
            
            // 更新Redis缓存记录成功结果
            if (jedisPool != null) {
                try (Jedis jedis = jedisPool.getResource()) {
                    int deduplicationTime = isTransfer ? 5 : 30;
                    String keyPrefix = isTransfer ? "jd_transfer_sent_" : "jd_callback_sent_";
                    String deduplicationKey = keyPrefix + order.getId() + "_" + status;
                    
                    Map<String, Object> successInfo = new HashMap<>();
                    successInfo.put("order_id", order.getId());
                    successInfo.put("status", status);
                    successInfo.put("sent_at", Instant.now().toString());
                    successInfo.put("timestamp", System.currentTimeMillis() / 1000);
                    successInfo.put("result", responseData);
                    successInfo.put("success", true);
                    successInfo.put("is_transfer", isTransfer);
                    
                    jedis.setex(deduplicationKey, deduplicationTime, objectMapper.writeValueAsString(successInfo));
                }
            }
            
            logger.info("海博技术服务平台回调发送成功 - 订单ID: {}, 平台订单号: {}, 状态: {}", 
                    order.getId(), order.getPlatformOrderNo(), status);
            
            CallbackResult result = new CallbackResult();
            result.setSuccess(true);
            result.setMessage("回调发送成功");
            result.setData(responseData);
            return result;
            
        } catch (Exception e) {
            // 清理Redis缓存，允许重试
            if (jedisPool != null) {
                try (Jedis jedis = jedisPool.getResource()) {
                    boolean isTransfer = Boolean.TRUE.equals(extraParams.get("isTransfer"));
                    String keyPrefix = isTransfer ? "jd_transfer_sent_" : "jd_callback_sent_";
                    String deduplicationKey = keyPrefix + order.getId() + "_" + status;
                    jedis.del(deduplicationKey);
                } catch (Exception redisException) {
                    logger.warn("清理Redis缓存失败: {}", redisException.getMessage());
                }
            }
            
            logger.error("海博技术服务平台回调发送失败 - 订单ID: {}, 平台订单号: {}, 状态: {}, 错误: {}", 
                    order.getId(), order.getPlatformOrderNo(), status, e.getMessage(), e);
            
            CallbackResult result = new CallbackResult();
            result.setSuccess(false);
            result.setMessage("回调发送失败: " + e.getMessage());
            return result;
        }
    }
    
    /**
     * 构建回调参数
     */
    private Map<String, Object> buildCallbackParams(Order order, int status, Map<String, Object> extraParams) {
        long operateTime = System.currentTimeMillis() / 1000;
        
        // 业务参数
        Map<String, Object> businessParams = new HashMap<>();
        businessParams.put("orderId", order.getPlatformOrderNo() != null ? order.getPlatformOrderNo() : order.getOrderNo());
        businessParams.put("carrierDeliveryId", order.getOrderNo());
        businessParams.put("carrierShopId", order.getJdStoreId());
        businessParams.put("carrierMerchantId", order.getCarrierMerchantId() != null ? order.getCarrierMerchantId() : "HBT_JZD");
        businessParams.put("status", status);
        businessParams.put("operateTime", operateTime);
        
        // 根据状态添加必要的骑手信息
        int[] riderRequiredStatuses = {20, 25, 30, 50};
        boolean requiresRider = Arrays.stream(riderRequiredStatuses).anyMatch(s -> s == status);
        
        if (requiresRider) {
            // 检查是否为转单操作
            if (Boolean.TRUE.equals(extraParams.get("isTransfer"))) {
                businessParams.put("riderName", extraParams.getOrDefault("newRiderName", ""));
                businessParams.put("riderPhone", extraParams.getOrDefault("newRiderPhone", ""));
                businessParams.put("riderPhoneType", 0);
            } else {
                // 从订单信息获取骑手信息
                if (order.getRiderName() != null) {
                    businessParams.put("riderName", order.getRiderName());
                }
                if (order.getRiderPhone() != null) {
                    businessParams.put("riderPhone", order.getRiderPhone());
                    businessParams.put("riderPhoneType", 0);
                }
            }
            
            // 处理位置信息
            if (businessParams.containsKey("riderName")) {
                if (extraParams.containsKey("riderLng") && extraParams.containsKey("riderLat")) {
                    businessParams.put("riderLng", formatCoordinate(extraParams.get("riderLng")));
                    businessParams.put("riderLat", formatCoordinate(extraParams.get("riderLat")));
                } else if (order.getRiderLng() != null && order.getRiderLat() != null) {
                    businessParams.put("riderLng", formatCoordinate(order.getRiderLng()));
                    businessParams.put("riderLat", formatCoordinate(order.getRiderLat()));
                } else {
                    // 使用默认位置（北京天安门）
                    businessParams.put("riderLng", 116397470);
                    businessParams.put("riderLat", 39908860);
                }
                
                // 验证并调整经纬度范围
                businessParams = validateCoordinates(businessParams);
            }
        }
        
        // 取消状态的特殊处理
        if (status == 99) {
            businessParams.put("cancelReasonCode", extraParams.getOrDefault("cancelReasonCode", 99));
            businessParams.put("cancelReasonDesc", extraParams.getOrDefault("cancelReasonDesc", "其他原因取消"));
            
            if (extraParams.containsKey("cancelFee")) {
                businessParams.put("cancelFee", ((Number) extraParams.get("cancelFee")).doubleValue());
            }
        }
        
        // 费用信息
        if (order.getFee() != null) {
            OrderFee fee = order.getFee();
            if (fee.getActualAmount() != null) {
                businessParams.put("actualFee", fee.getActualAmount());
            } else if (fee.getTotalAmount() != null) {
                businessParams.put("actualFee", fee.getTotalAmount());
            }
            
            if (fee.getTollFee() != null && fee.getTollFee() > 0) {
                businessParams.put("tollFee", fee.getTollFee());
            }
            if (fee.getHandlingFee() != null && fee.getHandlingFee() > 0) {
                businessParams.put("handlingFee", fee.getHandlingFee());
            }
            if (fee.getWaitingFee() != null && fee.getWaitingFee() > 0) {
                businessParams.put("waitingFee", fee.getWaitingFee());
            }
            if (fee.getParkingFee() != null && fee.getParkingFee() > 0) {
                businessParams.put("parkingFee", fee.getParkingFee());
            }
        }
        
        // 订单图片信息
        if (extraParams.containsKey("orderImages")) {
            Object orderImages = extraParams.get("orderImages");
            if (orderImages instanceof String) {
                businessParams.put("orderImages", orderImages);
            } else {
                try {
                    businessParams.put("orderImages", objectMapper.writeValueAsString(orderImages));
                } catch (Exception e) {
                    logger.warn("序列化订单图片失败: {}", e.getMessage());
                }
            }
        }
        
        // 添加公共参数
        Map<String, Object> commonParams = new HashMap<>();
        commonParams.put("developerId", config.getDeveloperId());
        commonParams.put("timestamp", System.currentTimeMillis() / 1000);
        commonParams.put("version", "1.0");
        
        // 合并参数
        Map<String, Object> allParams = new HashMap<>();
        allParams.putAll(commonParams);
        allParams.putAll(businessParams);
        
        // 生成签名
        allParams.put("sign", generateSign(allParams));
        
        return allParams;
    }
    
    /**
     * 生成签名
     */
    private String generateSign(Map<String, Object> params) {
        // 移除签名参数
        params.remove("sign");
        
        // 过滤空值参数
        Map<String, Object> filteredParams = new HashMap<>();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            Object value = entry.getValue();
            if (value != null && !value.equals("") && !(value instanceof Collection && ((Collection<?>) value).isEmpty())) {
                filteredParams.put(entry.getKey(), value);
            }
        }
        
        // 按参数名字典顺序排序
        TreeMap<String, Object> sortedParams = new TreeMap<>(filteredParams);
        
        // 拼接参数字符串
        StringBuilder stringToBeSigned = new StringBuilder();
        for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
            Object value = entry.getValue();
            String strValue;
            
            if (value instanceof Boolean) {
                strValue = value.toString();
            } else if (value instanceof Collection || value instanceof Map) {
                try {
                    strValue = objectMapper.writeValueAsString(value);
                } catch (Exception e) {
                    strValue = value.toString();
                }
            } else {
                strValue = value.toString();
            }
            
            stringToBeSigned.append(entry.getKey()).append(strValue);
        }
        
        // 加上secret前缀
        stringToBeSigned.insert(0, config.getSecret());
        
        // SHA1加密并转小写
        return sha1(stringToBeSigned.toString()).toLowerCase();
    }
    
    /**
     * SHA1加密
     */
    private String sha1(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            byte[] hash = digest.digest(input.getBytes("UTF-8"));
            StringBuilder hexString = new StringBuilder();
            
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException("SHA1加密失败", e);
        }
    }
    
    /**
     * 发送回调请求
     */
    private Map<String, Object> sendCallback(Map<String, Object> params) throws Exception {
        int retry = 0;
        Exception lastError = null;
        
        while (retry < MAX_RETRY) {
            try {
                if (retry > 0) {
                    logger.info("京东回调重试 - 第 {} 次重试 - 订单ID: {}, 状态: {}", 
                            retry, params.get("orderId"), params.get("status"));
                }
                
                String url = getCallbackUrl();
                HttpPost httpPost = new HttpPost(url);
                
                // 构建表单数据
                StringBuilder formData = new StringBuilder();
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    if (formData.length() > 0) {
                        formData.append("&");
                    }
                    formData.append(URLEncoder.encode(entry.getKey(), "UTF-8"))
                            .append("=")
                            .append(URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
                }
                
                StringEntity entity = new StringEntity(formData.toString(), "UTF-8");
                entity.setContentType("application/x-www-form-urlencoded");
                httpPost.setEntity(entity);
                
                httpPost.setHeader("User-Agent", config.getUserAgent());
                httpPost.setHeader("Accept", "application/json");
                
                long requestStartTime = System.currentTimeMillis();
                CloseableHttpResponse response = httpClient.execute(httpPost);
                long requestDuration = System.currentTimeMillis() - requestStartTime;
                
                try {
                    int statusCode = response.getStatusLine().getStatusCode();
                    String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
                    
                    logger.info("海博技术服务平台回调HTTP请求详情 - URL: {}, 耗时: {}ms, HTTP状态码: {}, 重试: {}", 
                            url, requestDuration, statusCode, retry);
                    
                    if (statusCode != HttpStatus.SC_OK) {
                        throw new Exception("HTTP状态码错误: " + statusCode + ", 响应: " + responseBody);
                    }
                    
                    Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
                    Integer code = (Integer) result.get("code");
                    
                    if (code != null && code == 0) {
                        if (retry > 0) {
                            logger.info("京东回调重试成功 - 第 {} 次重试成功 - 订单ID: {}, 状态: {}", 
                                    retry, params.get("orderId"), params.get("status"));
                        }
                        return result;
                    } else {
                        int errorCode = code != null ? code : -1;
                        String errorMsg = (String) result.getOrDefault("message", "未知错误");
                        
                        // 检查是否是不需要重试的错误码
                        int[] noRetryErrorCodes = {ERROR_CARRIER_MISMATCH, ERROR_DELIVERY_ID_MISMATCH, ERROR_WAYBILL_NOT_EXIST};
                        boolean shouldNotRetry = Arrays.stream(noRetryErrorCodes).anyMatch(ec -> ec == errorCode);
                        
                        if (shouldNotRetry) {
                            String errorDesc = getErrorDescription(errorCode);
                            throw new Exception("海博技术服务平台接口返回不重试错误: [" + errorCode + "] " + errorDesc + " - " + errorMsg);
                        }
                        
                        String errorDesc = getErrorDescription(errorCode);
                        throw new Exception("海博技术服务平台接口返回错误: [" + errorCode + "] " + errorDesc + " - " + errorMsg);
                    }
                    
                } finally {
                    response.close();
                }
                
            } catch (Exception e) {
                if (e.getMessage().contains("不重试错误")) {
                    throw e;
                }
                
                lastError = e;
                retry++;
                
                if (retry < MAX_RETRY) {
                    try {
                        Thread.sleep(retry * 1000);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new Exception("重试中断", ie);
                    }
                }
            }
        }
        
        throw new Exception("回调发送失败，已重试" + MAX_RETRY + "次: " + lastError.getMessage(), lastError);
    }
    
    /**
     * 获取回调URL
     */
    private String getCallbackUrl() {
        switch (config.getEnvironment()) {
            case "prod":
                return CALLBACK_URL_PROD;
            case "sandbox":
                return CALLBACK_URL_SANDBOX;
            case "test":
            default:
                return CALLBACK_URL_TEST;
        }
    }
    
    /**
     * 格式化坐标为京东API格式
     */
    private long formatCoordinate(Object coordinate) {
        if (coordinate instanceof Number) {
            double coord = ((Number) coordinate).doubleValue();
            // 如果已经是*10^6格式的整数，直接返回
            if (Math.abs(coord) > 1000000) {
                return ((Number) coordinate).longValue();
            }
            // 否则转换为*10^6格式
            return Math.round(coord * 1000000);
        }
        return 0;
    }
    
    /**
     * 验证并调整坐标范围
     */
    private Map<String, Object> validateCoordinates(Map<String, Object> params) {
        if (!params.containsKey("riderLng") || !params.containsKey("riderLat")) {
            return params;
        }
        
        long riderLng = ((Number) params.get("riderLng")).longValue();
        long riderLat = ((Number) params.get("riderLat")).longValue();
        
        // 处理负数经度
        if (riderLng < 0) {
            riderLng = 360000000L + riderLng;
        }
        
        // 验证经度范围 (0 < lng < 360000000)
        if (riderLng <= 0 || riderLng >= 360000000L) {
            riderLng = 116397470L; // 北京天安门
        }
        
        // 验证纬度范围 (-90000000 < lat < 90000000)
        if (riderLat < -90000000L || riderLat > 90000000L) {
            riderLat = 39908860L; // 北京天安门
        }
        
        params.put("riderLng", riderLng);
        params.put("riderLat", riderLat);
        
        return params;
    }
    
    /**
     * 获取错误码描述
     */
    private String getErrorDescription(int errorCode) {
        Map<Integer, String> errorMap = new HashMap<>();
        errorMap.put(ERROR_SUCCESS, "请求成功");
        errorMap.put(ERROR_SYSTEM_ERROR, "系统异常");
        errorMap.put(ERROR_PARAM_ERROR, "缺少参数，或参数格式错误");
        errorMap.put(ERROR_SIGN_ERROR, "签名验证失败");
        errorMap.put(ERROR_UNAUTHORIZED, "未授权或授权过期");
        errorMap.put(ERROR_RATE_LIMIT, "接口流控");
        errorMap.put(ERROR_OTHER, "其他原因");
        errorMap.put(ERROR_NO_CAPACITY, "该地区暂无运力");
        errorMap.put(ERROR_ORDER_NOT_EXIST, "订单不存在");
        errorMap.put(ERROR_ORDER_COMPLETED, "订单已完成，不能取消");
        errorMap.put(ERROR_SERVICE_NOT_OPEN, "门店未开通所选服务产品");
        errorMap.put(ERROR_OUT_OF_RANGE, "送货地址超出配送范围");
        errorMap.put(ERROR_APPOINTMENT_TIME, "预约时间内无法完成履约");
        errorMap.put(ERROR_CAPACITY_SHORTAGE, "运力紧张，无法创建订单");
        errorMap.put(ERROR_ACCOUNT_BALANCE, "账户余额不足或扣款失败");
        errorMap.put(ERROR_NO_APPOINTMENT, "暂不支持预约单");
        errorMap.put(ERROR_NO_REVERSE_ORDER, "暂不支持逆向发单");
        errorMap.put(ERROR_TIP_LIMIT, "骑手已接单，无法添加小费");
        errorMap.put(ERROR_TIP_MAX, "小费金额已至上限，无法继续添加");
        errorMap.put(ERROR_NO_RIDER_LOCATION, "骑手目前没有位置信息，请稍后重试");
        errorMap.put(ERROR_CARRIER_MISMATCH, "配送商不匹配");
        errorMap.put(ERROR_DELIVERY_ID_MISMATCH, "配送商物流单号不匹配");
        errorMap.put(ERROR_WAYBILL_NOT_EXIST, "运单不存在");
        errorMap.put(ERROR_RIDER_CODE_ERROR, "骑手信息错误，请扫正确的骑手码");
        errorMap.put(ERROR_RIDER_LIMIT, "骑手接单数已超上限");
        errorMap.put(ERROR_RIDER_CANNOT_ACCEPT, "骑手无法接单");
        errorMap.put(ERROR_FEATURE_NOT_OPEN, "请联系配送商客服开通功能后使用");
        errorMap.put(ERROR_STORE_CREATE_FAILED, "暂时无法创建门店或修改门店信息，需要稍后重试");
        errorMap.put(ERROR_STORE_NO_CHANGE, "此次变更未修改任何门店信息");
        
        return errorMap.getOrDefault(errorCode, "未知错误码: " + errorCode);
    }
    
    /**
     * 将本地状态转换为京东状态
     */
    public static int convertLocalStatusToJingdongStatus(String localStatus) {
        Map<String, Integer> statusMap = new HashMap<>();
        statusMap.put("1", 1);
        statusMap.put("10", 10);  // 待接单 => 已创建(待接单)
        statusMap.put("20", 20);  // 已接单 => 已接单
        statusMap.put("25", 25);  // 到达取货点 => 已到店
        statusMap.put("30", 30);  // 配送中 => 已取货
        statusMap.put("50", 50);  // 已完成 => 已送达
        statusMap.put("99", 99);  // 已取消 => 已取消
        
        return statusMap.getOrDefault(localStatus, 10);
    }
    
    /**
     * 根据取消角色获取京东取消原因代码
     */
    public static int getCancelReasonCode(String role) {
        Map<String, Integer> reasonMap = new HashMap<>();
        reasonMap.put("ADMIN", 1);        // 商户取消
        reasonMap.put("CUSTOMER", 2);     // 用户取消
        reasonMap.put("SYSTEM", 3);       // 系统取消
        reasonMap.put("RIDER", 4);        // 骑手取消
        reasonMap.put("CARRIER", 5);      // 配送商取消
        
        return reasonMap.getOrDefault(role, 99);
    }
    
    /**
     * 根据取消角色获取取消原因描述
     */
    public static String getCancelReasonDesc(String role, String remark) {
        Map<String, String> reasonDesc = new HashMap<>();
        reasonDesc.put("ADMIN", "商户取消");
        reasonDesc.put("CUSTOMER", "用户取消");
        reasonDesc.put("SYSTEM", "系统取消");
        reasonDesc.put("RIDER", "骑手取消");
        reasonDesc.put("CARRIER", "配送商取消");
        
        String baseDesc = reasonDesc.getOrDefault(role, "其他原因");
        
        if (remark != null && !remark.isEmpty()) {
            return baseDesc + "：" + remark;
        }
        
        return baseDesc;
    }
    
    /**
     * 根据取消角色获取取消原因描述（无备注）
     */
    public static String getCancelReasonDesc(String role) {
        return getCancelReasonDesc(role, null);
    }
    
    /**
     * 测试连通性
     */
    public ConnectivityResult testConnectivity() {
        String url = getCallbackUrl();
        return ConnectivityTester.test(url);
    }
    
    /**
     * 关闭资源
     */
    public void close() {
        try {
            if (httpClient != null) {
                httpClient.close();
            }
        } catch (IOException e) {
            logger.warn("关闭HTTP客户端失败: {}", e.getMessage());
        }
        
        if (jedisPool != null) {
            jedisPool.close();
        }
        
        logger.info("京东配送回调SDK资源已释放");
    }
}
